import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.provider.PrivacyProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smackx.GroupChatInvitation;
import org.jivesoftware.smackx.NodeInformationProvider;
import org.jivesoftware.smackx.PrivateDataManager;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.jivesoftware.smackx.commands.AdHocCommandManager;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.packet.AdHocCommandData;
import org.jivesoftware.smackx.packet.ChatStateExtension;
import org.jivesoftware.smackx.packet.DiscoverInfo;
import org.jivesoftware.smackx.packet.DiscoverItems;
import org.jivesoftware.smackx.packet.LastActivity;
import org.jivesoftware.smackx.packet.OfflineMessageInfo;
import org.jivesoftware.smackx.packet.OfflineMessageRequest;
import org.jivesoftware.smackx.packet.SharedGroupsInfo;
import org.jivesoftware.smackx.packet.DiscoverInfo.Identity;
import org.jivesoftware.smackx.provider.AdHocCommandDataProvider;
import org.jivesoftware.smackx.provider.BytestreamsProvider;
import org.jivesoftware.smackx.provider.DataFormProvider;
import org.jivesoftware.smackx.provider.DelayInformationProvider;
import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
import org.jivesoftware.smackx.provider.DiscoverItemsProvider;
import org.jivesoftware.smackx.provider.IBBProviders;
import org.jivesoftware.smackx.provider.MUCAdminProvider;
import org.jivesoftware.smackx.provider.MUCOwnerProvider;
import org.jivesoftware.smackx.provider.MUCUserProvider;
import org.jivesoftware.smackx.provider.MessageEventProvider;
import org.jivesoftware.smackx.provider.MultipleAddressesProvider;
import org.jivesoftware.smackx.provider.RosterExchangeProvider;
import org.jivesoftware.smackx.provider.StreamInitiationProvider;
import org.jivesoftware.smackx.provider.VCardProvider;
import org.jivesoftware.smackx.provider.XHTMLExtensionProvider;
import org.jivesoftware.smackx.search.UserSearch;


public class DiscoUseCase {

	private static String USERNAME = "andi";
	private static String PASSWORD = "andi";
	private static String SERVER = "blindeshendl.cg.tuwien.ac.at";
	
	
	

	//private static String SERVER = "JabberIM.de";
	//private static String USERNAME = "test1234";
	//private static String PASSWORD = "test1234";

	private static String SENDTO = "peter@blindeshendl.cg.tuwien.ac.at";
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		
		ProviderManager pm = ProviderManager.getInstance();
		//configure the provider manager (adding extensions that are implemented in smack)
		configure(pm);
		//add our custom extension
		pm.addIQProvider("query", MyIQPacket.FEATURE_NAMESPACE, new MyIQProvider());

		XMPPConnection.DEBUG_ENABLED = true;

		
		
		
		final Connection connection = new XMPPConnection(SERVER);
		ServiceDiscoveryManager discoManager = null;
		AdHocCommandManager adHocCommandManager = null;

		//create custom extension manager
		MyExtensionManager em = new MyExtensionManager(connection);
		
		
		
		//connect
		try {
			
			
			// Obtain the ServiceDiscoveryManager associated with my XMPPConnection
			// This actually yields a null pointer! (strange behavior of smack!?). 
			// It however triggers the static block of this class initializing an instance.
			// Therefore it must not be removed here!
			discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
			// Obtain the AdHocCommandManager associated with my XMPPConnection
			// This actually yields a null pointer! (strange behavior of smack!?). 
			// It however triggers the static block of this class initializing an instance.
			// Therefore it must not be removed here!
			adHocCommandManager = AdHocCommandManager.getAddHocCommandsManager(connection);

			//establish the connection to the server
			connection.connect();
			
			//Due to the strange behavior of smack we get the pointers to the managers in the following.
			//The first calls to the getInstance functions do not return an instance of the managers but null!
			//However, they have to be called in order to trigger the class loader (and the static block). 
			//This creates instances of the managers and we can finally retrieve them here (calling the same commands a second time).
			discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
			adHocCommandManager = AdHocCommandManager.getAddHocCommandsManager(connection);
			
			
			// Register a new feature with the disco manager.
			// We use this to announce our custom extension.
			discoManager.addFeature(MyIQPacket.FEATURE_NAMESPACE);

		} catch (XMPPException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(-1);
		} 
		//login
		try {
			connection.login(USERNAME, PASSWORD);
		} catch (XMPPException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		
		adHocCommandManager = AdHocCommandManager.getAddHocCommandsManager(connection);
		adHocCommandManager.registerCommand(MyLocalCommand.class.getCanonicalName(), MyLocalCommand.HUMANREADABLENAME, MyLocalCommand.class);
		
		System.out.println("command name: " +MyLocalCommand.class.getCanonicalName());

		try {
			Thread.sleep(1000000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if((connection!=null)&&(connection.isConnected())) {
			connection.disconnect();
		}
	}


	/**
	 * Sets the extension providers for the smack library.
	 * This function is a bugfix described here:
	 * http://www.igniterealtime.org/community/message/201866
	 *  
	 * @param pm The ProviderManager 
	 */

	public static void configure(ProviderManager pm) {

		//  Private Data Storage
		pm.addIQProvider("query","jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider());


		//  Time
		/*
		 * not working in asmack

		try {

			pm.addIQProvider("query","jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time"));
		} catch (ClassNotFoundException e) {
			System.out.println("Can't load class for org.jivesoftware.smackx.packet.Time");
		}
		 */

		//  Roster Exchange
		pm.addExtensionProvider("x","jabber:x:roster", new RosterExchangeProvider());

		//  Message Events
		pm.addExtensionProvider("x","jabber:x:event", new MessageEventProvider());

		//  Chat State
		pm.addExtensionProvider("active","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());

		pm.addExtensionProvider("composing","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());

		pm.addExtensionProvider("paused","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());

		pm.addExtensionProvider("inactive","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());

		pm.addExtensionProvider("gone","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());

		//  XHTML
		pm.addExtensionProvider("html","http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider());

		//  Group Chat Invitations
		pm.addExtensionProvider("x","jabber:x:conference", new GroupChatInvitation.Provider());

		//  Service Discovery # Items    
		pm.addIQProvider("query","http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());

		//  Service Discovery # Info
		pm.addIQProvider("query","http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());

		//  Data Forms
		pm.addExtensionProvider("x","jabber:x:data", new DataFormProvider());

		//  MUC User
		pm.addExtensionProvider("x","http://jabber.org/protocol/muc#user", new MUCUserProvider());

		//  MUC Admin    
		pm.addIQProvider("query","http://jabber.org/protocol/muc#admin", new MUCAdminProvider());


		//  MUC Owner    
		pm.addIQProvider("query","http://jabber.org/protocol/muc#owner", new MUCOwnerProvider());

		/*
		 * not working for asmack 
		 * 

		//  Delayed Delivery
		pm.addExtensionProvider("x","jabber:x:delay", new DelayInformationProvider());
		 */

		/*
		 * not working for asmack 
		 * 

		//  Version
		try {
			pm.addIQProvider("query","jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version"));
		} catch (ClassNotFoundException e) {
			//  Not sure what's happening here.
		}
		 */

		//  VCard
		pm.addIQProvider("vCard","vcard-temp", new VCardProvider());

		//  Offline Message Requests
		pm.addIQProvider("offline","http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider());

		//  Offline Message Indicator
		pm.addExtensionProvider("offline","http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider());

		//  Last Activity
		pm.addIQProvider("query","jabber:iq:last", new LastActivity.Provider());

		//  User Search
		pm.addIQProvider("query","jabber:iq:search", new UserSearch.Provider());

		//  SharedGroupsInfo
		pm.addIQProvider("sharedgroup","http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider());

		//  JEP-33: Extended Stanza Addressing
		pm.addExtensionProvider("addresses","http://jabber.org/protocol/address", new MultipleAddressesProvider());

		//   FileTransfer
		pm.addIQProvider("si","http://jabber.org/protocol/si", new StreamInitiationProvider());

		pm.addIQProvider("query","http://jabber.org/protocol/bytestreams", new BytestreamsProvider());

		pm.addIQProvider("open","http://jabber.org/protocol/ibb", new IBBProviders.Open());

		pm.addIQProvider("close","http://jabber.org/protocol/ibb", new IBBProviders.Close());

		pm.addExtensionProvider("data","http://jabber.org/protocol/ibb", new IBBProviders.Data());

		//  Privacy
		pm.addIQProvider("query","jabber:iq:privacy", new PrivacyProvider());

		pm.addIQProvider("command", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider());
		pm.addExtensionProvider("malformed-action", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.MalformedActionError());
		pm.addExtensionProvider("bad-locale", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadLocaleError());
		pm.addExtensionProvider("bad-payload", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadPayloadError());
		pm.addExtensionProvider("bad-sessionid", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadSessionIDError());
		pm.addExtensionProvider("session-expired", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.SessionExpiredError());


	}



}
